package repository

import (
	"ecms/database/mysql"
	"ecms/utils/reflects"
	"fmt"
	"strings"
)

type Repository struct {
	model interface{}
}

func New(model interface{}) *Repository {
	return &Repository{model: model}
}

// FindById 根据ID查询单条
func (r *Repository) FindById(id interface{}, out interface{}) bool {
	if err := mysql.Conn().Model(r.model).Where("id = ?", id).Find(out).Error; err != nil {
		return false
	}
	return true
}

// FindByField 根据字段查询单条
func (r *Repository) FindByField(field string, value interface{}, out interface{}) bool {
	if err := mysql.Conn().Model(r.model).Where(fmt.Sprintf("%s = ?", field), value).Find(out).Error; err != nil {
		return false
	}
	return true
}

// Find 自定义条件查询单条
func (r Repository) Find(out interface{}, query string, args ...interface{}) bool {
	if err := mysql.Conn().Model(r.model).Where(query, args...).Find(out).Error; err != nil {
		return false
	}
	return true
}

// SelectAll 查询全部符合条件的
func (r *Repository) SelectAll(order string, out interface{}, query string, args ...interface{}) bool {
	if err := mysql.Conn().Model(r.model).Where(query, args...).Order(order).Find(out).Error; err != nil {
		return false
	}
	return true
}

// Create 创建单条数据记录
func (r *Repository) Create(data interface{}) bool {
	if err := mysql.Conn().Model(r.model).Create(data).Error; err != nil {
		return false
	}
	return true
}

// DeleteById 根据ID删除单条
func (r *Repository) DeleteById(id interface{}) bool {
	result := mysql.Conn().Model(r.model).Where("id = ?", id).Update("is_deleted", 1)
	if result.Error != nil || result.RowsAffected == 0 {
		return false
	}
	return true
}

// DeleteByField 根据字段删除单条
func (r *Repository) DeleteByField(field string, val interface{}) bool {
	result := mysql.Conn().Model(r.model).Where(fmt.Sprintf("%s = ?", field), val).Update("is_deleted", 1)
	if result.Error != nil || result.RowsAffected == 0 {
		return false
	}
	return true
}

// Delete 自定义条件删除
func (r *Repository) Delete(query string, args ...interface{}) bool {
	result := mysql.Conn().Model(r.model).Where(query, args...).Update("is_deleted", 1)
	if result.Error != nil || result.RowsAffected == 0 {
		return false
	}
	return true
}

// UpdateById 根据ID更新
func (r *Repository) UpdateById(id interface{}, data interface{}) bool {
	refObj, err := reflects.NewObject(data)
	if err != nil {
		return false
	}
	saveData := refObj.GenerateMap()
	if err := mysql.Conn().Model(r.model).Where("id = ?", id).Updates(saveData).Error; err != nil {
		return false
	}
	return true
}

// UpdateByField 根据字段更新
func (r *Repository) UpdateByField(field string, val interface{}, data interface{}) bool {
	refObj, err := reflects.NewObject(data)
	if err != nil {
		return false
	}
	saveData := refObj.GenerateMap()
	if err := mysql.Conn().Model(r.model).Where(fmt.Sprintf("%s = ?", field), val).Updates(saveData).Error; err != nil {
		return false
	}
	return true
}

// Update 自定义条件更新
func (r *Repository) Update(query string, data interface{}, args ...interface{}) bool {
	refObj, err := reflects.NewObject(data)
	if err != nil {
		return false
	}
	saveData := refObj.GenerateMap()
	if err := mysql.Conn().Model(r.model).Where(query, args...).Updates(saveData).Error; err != nil {
		return false
	}
	return true
}

// EnableById 根据ID启用
func (r *Repository) EnableById(id interface{}) bool {
	result := mysql.Conn().Model(r.model).Where("id = ?", id).Update("status", 1)
	if result.Error != nil || result.RowsAffected == 0 {
		return false
	}
	return true
}

// EnableByField 根据字段启用
func (r *Repository) EnableByField(field string, val interface{}) bool {
	result := mysql.Conn().Model(r.model).Where(fmt.Sprintf("%s = ?", field), val).Update("status", 1)
	if result.Error != nil || result.RowsAffected == 0 {
		return false
	}
	return true
}

// Enable 自定义条件启用
func (r *Repository) Enable(query string, args ...interface{}) bool {
	result := mysql.Conn().Model(r.model).Where(query, args...).Update("status", 1)
	if result.Error != nil || result.RowsAffected == 0 {
		return false
	}
	return true
}

// DisableById 根据ID禁用
func (r *Repository) DisableById(id interface{}) bool {
	result := mysql.Conn().Model(r.model).Where("id = ?", id).Update("status", 0)
	if result.Error != nil || result.RowsAffected == 0 {
		return false
	}
	return true
}

// DisableByField 根据字段禁用
func (r *Repository) DisableByField(field string, val interface{}) bool {
	result := mysql.Conn().Model(r.model).Where(fmt.Sprintf("%s = ?", field), val).Update("status", 0)
	if result.Error != nil || result.RowsAffected == 0 {
		return false
	}
	return true
}

// Disable 自定义条件禁用
func (r *Repository) Disable(query string, args ...interface{}) bool {
	result := mysql.Conn().Model(r.model).Where(query, args...).Update("status", 0)
	if result.Error != nil || result.RowsAffected == 0 {
		return false
	}
	return true
}

type PaginationQuery struct {
	Out      interface{}
	Page     int
	PageSize int
	Query    string
	Count    *int64
	Args     []interface{}
	Order    string
}

// Pagination 分页数据列表
func (r *Repository) Pagination(query *PaginationQuery) bool {
	offset := (query.Page - 1) * query.PageSize
	if err := mysql.Conn().Model(r.model).Where(query.Query, query.Args...).
		Count(query.Count).Order(query.Order).
		Offset(offset).Limit(query.PageSize).Find(query.Out).Error; err != nil {
		return false
	}
	return true
}

// BuildSearchQuery 构建搜索词
func (r *Repository) BuildSearchQuery(baseQuery *string, fields []string, keyword string, args *[]interface{}) {
	queryFields := make([]string, 0)
	keyword = fmt.Sprintf("%%%s%%", keyword)
	for _, v := range fields {
		queryFields = append(queryFields, fmt.Sprintf("%s LIKE ?", v))
		*args = append(*args, keyword)
	}
	*baseQuery += fmt.Sprintf(" AND (%s)", strings.Join(queryFields, " OR "))
}
